package com.xltt.bluetoothlib.ble;



import android.bluetooth.BluetoothDevice;
import android.util.Log;

import com.xltt.bluetoothlib.ble.event.OnChangeEvent;
import com.xltt.bluetoothlib.ble.utils.HexUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class DataPackage {
    /**
     * 数据包监听
     */
    public interface OnDataPackageListener {
        void OnDataPackage(OnChangeEvent changeEvent);//监听数据包
        void onConnectionStateChange(BluetoothDevice device, int status, int newState);//连接状态
    }

    public static byte[] getPacketDataLength(byte[] data) {
        byte[] newData = new byte[2];
        System.arraycopy(data, 6, newData, 0, 2);
        return newData;
    }
    

    /**
     * 字节数组转HexString
     *
     * @param buff
     * @return
     */
    public static String[] getHexStrings(byte[] buff) {
        List<String> templist = new ArrayList<>();
        for (int i = 0; i < buff.length; i++) {
            String hex = Integer.toHexString(buff[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            hex = "0x" + hex;
            templist.add(hex);
        }
        return templist.toArray(new String[0]);
    }

    /**
     * LRC校验
     * @param packetData
     * @return
     */
    private static byte calculateChecksum(byte[] packetData) {
        byte value = packetData[0];
        for (int i = 1; i < packetData.length; i++) {
            value = (byte) (value ^ packetData[i]);
        }
        return value;
    }

    /**
     * 把src的数据追加到dest后面
     *
     * @param dest 目标数组
     * @param src  要加入目标的新数组
     * @param pos  新数组的截取的开始
     * @param len  新数组截取的长度
     */
    public static byte[] add(byte[] dest, byte[] src, int pos, int len) {
        dest = Arrays.copyOf(dest, dest.length + len);
        System.arraycopy(src, pos, dest, dest.length - len, len);
        return dest;
    }

    /**
     * 发送包
     * @param cmd 主指令
     * @param index 索引
     * @param dataBody 可变数据
     * @return
     */
    public static byte[] sendPacket(byte[] cmd, byte[] index,byte[] dataBody) {
        byte[] newData = new byte[0];//封装的数据 10
        if (cmd != null) {
            newData = add(newData, cmd, 0, cmd.length);//主指令
            newData = add(newData, index, 0, index.length);//包索引
            if (dataBody != null) {
                //有数据体
                newData = add(newData, HexUtil.shortToByteLittle((short) dataBody.length), 0, 2);//可变数据长度
                newData = add(newData, dataBody, 0, dataBody.length);//数据体
            } else {
                //无数据体
                newData = add(newData, HexUtil.shortToByteLittle((short) dataBody.length), 0, 2);//可变数据长度
            }
            newData = add(newData, new byte[]{(byte) (calculateChecksum(newData))}, 0, 1);
        }
        return newData;
    }


    /**
     * 解析数据
     * 主指令号	1字节
     * 包索引标识	 1字节
     * 数据长度	2字节
     * 可变数据	不定长
     * LRC(异或校验) 1字节
     * @param data
     * @return
     */
    public static byte[] getBodyData(byte[] data) {
        byte[] newData = new byte[data.length - 5];
        System.arraycopy(data, 4, newData, 0, data.length - 5);
        return newData;
    }


    /**
     * 获取一级指令
     * @param data
     * @return
     */
    public static byte[] getCommand(byte[] data) {
        byte[] newData = new byte[1];
        System.arraycopy(data, 0, newData, 0, 1);
        return newData;
    }

    /**
     * 获取包总长度
     * @param data
     * @return
     */
    public static byte[] getPacketLength(byte[] data) {
        byte[] newData = new byte[2];
        System.arraycopy(data, 2, newData, 0, 2);
        return newData;
    }

    /**
     * 获取二级指令
     * @param data
     * @return
     */
    public static byte[] getSecondaryCommand(byte[] data) {
        byte[] newData = new byte[1];
        System.arraycopy(data, 4, newData, 0, 1);
        return newData;
    }




    //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    //定义通信协议字段字节长度
    public static final int MAIN_CMMAND_LENGTH = 1;//主指令
    public static final int PACKET_INDEX_LENGTH = 1;//包索引
    public static final int DATA_LENGTH_LENGTH = 2;//数据长度
    public static final int CHECKSUM_LENGTH = 1;//LRC校验
    public static final int DATA_OFFSET = MAIN_CMMAND_LENGTH + PACKET_INDEX_LENGTH + DATA_LENGTH_LENGTH;//可变数据
    public static final int PACKET_LENGTH_OFFSET = MAIN_CMMAND_LENGTH + PACKET_INDEX_LENGTH;

    //定义通信协议字段索引
    public static final int MAIN_CMMAND_INDEX = 0;
    public static final int PACKET_INDEX_INDEX = MAIN_CMMAND_LENGTH;
    public static final int DATA_LENGTH_INDEX = MAIN_CMMAND_LENGTH + PACKET_INDEX_LENGTH;
    public static final int CHECKSUM_INDEX = DATA_OFFSET;
    public static final int DATA_INDEX = DATA_OFFSET + CHECKSUM_LENGTH;

    //定义通信协议包的最大长度(包总字节数据不超过500字节，无头尾标识，不需要转义)
    public static final int MAX_PACKET_LENGTH = 500;




    /**
     * 发送数据包
     * @param packetIndex  包索引
     * @param data    需要发送的数据
     * @throws IOException
     */
    public static byte[] sendPacket2(byte cmmand,int packetIndex,byte[] data) throws IOException {
        //计算数据包长度
        int packetLength = DATA_OFFSET + data.length + CHECKSUM_LENGTH;
        if(packetLength > MAX_PACKET_LENGTH){
            throw new IllegalArgumentException("发送数据包大于 " + MAX_PACKET_LENGTH + ",当前需要发送包长度 = " + data.length);
        }
        //构建数据包
        byte[] packetData = new byte[packetLength];
        packetData[MAIN_CMMAND_INDEX] = cmmand;
        packetData[PACKET_INDEX_INDEX] = (byte)packetIndex;
        packetData[DATA_LENGTH_INDEX] = (byte)(data.length >> 8);
        packetData[DATA_LENGTH_INDEX + 1] = (byte)(data.length);
        System.arraycopy(data,0,packetData,DATA_INDEX,data.length);
        packetData[CHECKSUM_INDEX] = calculateChecksum(packetData);
        return packetData;
    }



}
